/*
 * Digital Audio Mobile - A multi track studio for Windows Mobile
 * Copyright (C) 2008 David Olsson
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "Composition.h"
#include "Segment.h"
#include "Track.h"

using namespace std;

Track::Track(Composition *parent, const TCHAR *name) throw(): m_parent(parent), m_name(0), m_volume(255), m_pan(0), m_muted(false), m_hBrush(0), m_hUnselBrush(0) {
    m_name = new TCHAR[_tcslen(name) + 1];
    _tcscpy(m_name, name);

    m_hBrush = CreateSolidBrush(TRACKCOLORS[s_colorIndex]);
    m_hUnselBrush = CreateSolidBrush(mix(TRACKCOLORS[s_colorIndex], GetSysColor(COLOR_WINDOW)));
    if(TRACKCOLORS[++s_colorIndex] == 0) {
        s_colorIndex = 0;
    }
}

Track::~Track() {
    for(list<Segment *>::iterator iter = m_segments.begin(); iter != m_segments.end(); iter++) {
        delete(*iter);
    }
    if(m_hUnselBrush != 0) {
        DeleteObject(m_hUnselBrush);
    }
    if(m_hBrush != 0) {
        DeleteObject(m_hBrush);
    }
    if(m_name != 0) {
        delete[](m_name);
    }
}

const TCHAR *Track::name() const throw() {
    return(m_name);
}

void Track::setName(const TCHAR *name) throw() {
    if(m_name != 0) {
        delete[](m_name);
    }

    m_name = new TCHAR[_tcslen(name) + 1];
    _tcscpy(m_name, name);

    m_parent->setModified();
}

unsigned char Track::volume() const throw() {
    return(m_volume);
}

void Track::setVolume(unsigned char vol) throw() {
    m_volume = vol;
    m_parent->setModified();
}

char Track::pan() const throw() {
    return(m_pan);
}

void Track::setPan(char pan) throw() {
    m_pan = pan;
    m_parent->setModified();
}

HBRUSH Track::brush() const throw() {
    return(m_hBrush);
}

HBRUSH Track::unselectedBrush() const throw() {
    return(m_hUnselBrush);
}

bool Track::muted() const throw() {
    return(m_muted);
}

void Track::toggleMute() throw() {
    m_muted = !m_muted;
}

void Track::addSegment(Segment *seg) throw() {
    m_segments.push_back(seg);
    m_parent->setModified();
}

void Track::unlinkSegment(Segment *seg) throw() {
    m_segments.remove(seg);
    seg->unlink();
    m_parent->setModified();
}

void Track::unlinkSegments() throw() {
    while(!m_segments.empty()) {
        unlinkSegment(m_segments.back());
    }
}

const list<Segment *> &Track::segments() const throw() {
    return(m_segments);
}

void Track::superPositionSegments(AudioBuffer *buffer, const MusicTime &bufferStart) throw() {
    if(!m_muted) {
        for(list<Segment *>::iterator iter = m_segments.begin(); iter != m_segments.end(); iter++) {
            (*iter)->superPosition(buffer, bufferStart, m_volume);
        }
    }
}

COLORREF Track::mix(COLORREF a, COLORREF b) throw() {
    unsigned int mb = ((a >> 16) & 0xff) + ((b >> 16) & 0xff);
    unsigned int mg = ((a >> 8) & 0xff) + ((b >> 8) & 0xff);
    unsigned int mr = (a & 0xff) + (b & 0xff);
    return(RGB(mr / 2, mg / 2, mb / 2));
}

unsigned int Track::s_colorIndex = 0;

const COLORREF Track::TRACKCOLORS[] = {
    RGB(255, 128, 128),
    RGB(128, 255, 128),
    RGB(128, 128, 255),
    0
};
